#pragma once
#include <poll.h>
#include "Socket.hpp"

const static int gsize = sizeof(fd_set) * 8;
const static int gdefaultfd = -1;

class SelectServer
{
public:
    SelectServer(uint16_t port) : _listenfd(std::make_unique<TcpSocket>())
    {
        _listenfd->BuildTcpSocket(port);
        for (int i = 0; i < gsize; i++)
        {
            fd_arry[i].fd=gdefaultfd;
            fd_arry[i].events=fd_arry[i].revents=0;
        }
        fd_arry[0].fd = _listenfd->SockFd();
        fd_arry[0].events=POLLIN;
    }
    void Accepter()
    {
        InetAddr clientaddr;
        int sockfd = _listenfd->Accept(&clientaddr);
        if (sockfd > 0)
        {
            LOG(LogLevel::INFO) << "获取新连接成功，sockfd: " << sockfd << ",client addr: " << clientaddr.ToString();
            int i = 0;
            for (; i < gsize; i++)
            {
                if (fd_arry[i].fd = gdefaultfd)
                {
                    fd_arry[i].fd = sockfd;
                    fd_arry[i].events=POLLIN;
                    break;
                }
            }
            if (i == gsize)
            {
                LOG(LogLevel::WARING) << "fd_arry已满";
                close(sockfd);
            }
        }
    }
    void Recver(int index)
    {
        int sockfd = fd_arry[index].fd;
        char buffer[1024];
        // 这里读取，会不会阻塞？不会！
        // 这里的读取有问题！
        ssize_t n = recv(sockfd, buffer, sizeof(buffer), 0);
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << "client say@ " << buffer << std::endl;
            std::string echo_string = "server echo# ";
            echo_string += buffer;
            send(sockfd, echo_string.c_str(), echo_string.size(), 0); // ?
        }
        else if (n == 0)
        {
            LOG(LogLevel::INFO) << "client quit, me too: " << fd_arry[index].fd;
            fd_arry[index].fd = gdefaultfd;
            fd_arry[index].events=fd_arry[index].revents=0;
            close(sockfd);
        }
        else
        {
            LOG(LogLevel::WARING) << "recv error: " << fd_arry[index].fd;
            fd_arry[index].fd = gdefaultfd;
            fd_arry[index].events=fd_arry[index].revents=0;
            close(sockfd);
        }
    }
    void TaskDispatcher()
    {
        LOG(LogLevel::INFO) << "有新事件到来";
        for (int i = 0; i < gsize; i++)
        {
            if (fd_arry[i].fd == gdefaultfd)
                continue;
            if (fd_arry[i].revents&POLLIN)
            {
                if (fd_arry[i].fd == _listenfd->SockFd())
                {
                    Accepter();
                }
                else
                {
                    Recver(i);
                }
            }
        }
    }
    void Run()
    {
        while (true)
        {
            int timeout=-1;
            int n = poll(fd_arry,gsize,timeout);
            switch (n)
            {
            case 0:
                LOG(LogLevel::WARING) << "timeout...";
                break;
            case -1:
                LOG(LogLevel::ERRO) << "select错误";
                break;
            default:
                TaskDispatcher();
                break;
            }
        }
    }
    ~SelectServer() {}

private:
    std::unique_ptr<Socket> _listenfd;
    // int fd_arry[gsize];
    struct pollfd fd_arry[gsize];
};